package com.example.backend.security;

import com.example.backend.domain.entity.User;
import com.example.backend.service.AuthService;
import com.example.backend.util.PermissionDiagnosticTool;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 权限拦截器
 * 检查用户是否有访问特定API的权限
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(PermissionInterceptor.class);

    @Autowired
    private AuthService authService;
    
    @Autowired
    private PermissionDiagnosticTool diagnosticTool;
    
    @Value("${permission.diagnostic.enabled:true}")
    private boolean diagnosticEnabled;


    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        
        // 只处理方法级别的权限检查
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        RequirePermission requirePermission = handlerMethod.getMethodAnnotation(RequirePermission.class);
        
        // 如果没有权限注解，直接通过
        if (requirePermission == null) {
            return true;
        }

        try {
            // 获取当前用户
            String token = extractTokenFromRequest(request);
            User currentUser = authService.validateToken(token);
            
            if (currentUser == null) {
                log.warn("权限验证失败 - 用户未认证: uri={}", request.getRequestURI());
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"success\":false,\"message\":\"用户未认证或Token无效\"}");
                return false;
            }
            
            // 记录权限验证开始
            log.debug("╔══════════════════════════════════════════════════════");
            log.debug("║ 权限验证开始");
            log.debug("╠══════════════════════════════════════════════════════");
            log.debug("║ 请求信息: {} {}", request.getMethod(), request.getRequestURI());
            log.debug("║ 用户信息: 用户名={}, 角色={}, ID={}", 
                currentUser.getUsername(), 
                currentUser.getRole(),
                currentUser.getId());
            log.debug("║ 权限要求: 需要角色={}, 需要权限={}", 
                Arrays.toString(requirePermission.roles()),
                Arrays.toString(requirePermission.value()));
            log.debug("║ 处理方法: {}.{}", 
                handlerMethod.getMethod().getDeclaringClass().getSimpleName(),
                handlerMethod.getMethod().getName());
            log.debug("╚══════════════════════════════════════════════════════");
            
            // 检查角色权限
            if (requirePermission.roles().length > 0) {
                // 深度诊断（如果启用）
                if (diagnosticEnabled) {
                    Map<String, Object> diagnostic = diagnosticTool.diagnoseUserPermissions(
                        currentUser, requirePermission.roles(), request.getRequestURI());
                    diagnosticTool.printDiagnosticReport(diagnostic);
                }
                
                if (!hasRequiredRole(currentUser, requirePermission.roles())) {
                    log.warn("╔══════════════════════════════════════════════════════");
                    log.warn("║ ❌ 权限验证失败 - 角色不匹配");
                    log.warn("╠══════════════════════════════════════════════════════");
                    log.warn("║ 用户: {} (ID: {})", currentUser.getUsername(), currentUser.getId());
                    log.warn("║ 当前角色: {} (小写: {})", 
                        currentUser.getRole(), 
                        currentUser.getRole().name().toLowerCase());
                    log.warn("║ 需要角色: {}", Arrays.toString(requirePermission.roles()));
                    log.warn("║ 需要角色（小写）: {}", 
                        (Object) Arrays.stream(requirePermission.roles())
                            .map(String::toLowerCase)
                            .toArray(String[]::new));
                    log.warn("║ 请求URI: {}", request.getRequestURI());
                    log.warn("║ 处理方法: {}.{}", 
                        handlerMethod.getMethod().getDeclaringClass().getSimpleName(),
                        handlerMethod.getMethod().getName());
                    log.warn("╚══════════════════════════════════════════════════════");
                    
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(String.format(
                        "{\"success\":false,\"message\":\"权限不足: 需要角色 %s，当前角色 %s\"}",
                        Arrays.toString(requirePermission.roles()),
                        currentUser.getRole().name()
                    ));
                    return false;
                }
            }
            
            // 检查功能权限
            if (requirePermission.value().length > 0) {
                List<String> userPermissions = authService.getUserPermissions(token);
                if (!hasRequiredPermission(userPermissions, requirePermission.value(), requirePermission.mode())) {
                    log.warn("权限验证失败 - 权限不足: 用户={}, 用户权限={}, 需要权限={}, 模式={}, uri={}", 
                        currentUser.getUsername(), 
                        userPermissions,
                        Arrays.toString(requirePermission.value()),
                        requirePermission.mode(),
                        request.getRequestURI());
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write("{\"success\":false,\"message\":\"权限不足\"}");
                    return false;
                }
            }
            
            log.debug("╔══════════════════════════════════════════════════════");
            log.debug("║ ✓ 权限验证成功");
            log.debug("╠══════════════════════════════════════════════════════");
            log.debug("║ 用户: {} (角色: {})", currentUser.getUsername(), currentUser.getRole());
            log.debug("║ 请求: {} {}", request.getMethod(), request.getRequestURI());
            log.debug("║ 处理方法: {}.{}", 
                handlerMethod.getMethod().getDeclaringClass().getSimpleName(),
                handlerMethod.getMethod().getName());
            log.debug("╚══════════════════════════════════════════════════════");
            
            return true;
            
        } catch (Exception e) {
            // 不泄露详细错误信息到前端
            log.error("权限验证异常: uri={}, user={}, error={}", 
                request.getRequestURI(), 
                request.getHeader("Authorization") != null ? "已认证" : "未认证",
                e.getMessage(), 
                e);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"success\":false,\"message\":\"认证失败\"}");
            return false;
        }
    }

    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        throw new RuntimeException("无效的认证令牌");
    }

    private boolean hasRequiredRole(User user, String[] requiredRoles) {
        // 管理员账户始终拥有所有权限
        if (user.getRole() == com.example.backend.domain.enums.Role.ADMIN) {
            log.debug("管理员账户自动通过权限检查");
            return true;
        }
        
        String userRole = user.getRole().name().toLowerCase();
        return Arrays.stream(requiredRoles)
                .anyMatch(role -> role.toLowerCase().equals(userRole));
    }

    private boolean hasRequiredPermission(List<String> userPermissions, String[] requiredPermissions, RequirePermission.Mode mode) {
        if (mode == RequirePermission.Mode.ALL) {
            return Arrays.stream(requiredPermissions)
                    .allMatch(userPermissions::contains);
        } else {
            return Arrays.stream(requiredPermissions)
                    .anyMatch(userPermissions::contains);
        }
    }
}
